package cn.ts.utils;

import cn.ts.annotation.RateLimit;
import cn.ts.aspect.AbstractRateLimiter;
import cn.ts.entity.RateLimiterEntity;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author: ts
 * @description
 * @create: 2025/3/10 15:01
 */
@Slf4j
@Component("guavaRateLimiter")

public class GuavaRateLimiter extends AbstractRateLimiter {

    private final Cache<String, RateLimiter> rateLimiters = CacheBuilder.newBuilder()
            .expireAfterWrite(10, TimeUnit.SECONDS)
            .build();

    // 个人限频黑名单24h - 分布式业务场景，可以记录到 Redis 中
    private final Cache<String, Long> blacklist = CacheBuilder.newBuilder()
            .expireAfterWrite(24, TimeUnit.HOURS)
            .build();


    @Override
    protected  boolean limit(RateLimiterEntity rateLimiterEntity) throws ExecutionException {

        RateLimit rateLimit = rateLimiterEntity.getRateLimit();

        String key = rateLimiterEntity.getKey();

        String userId = rateLimiterEntity.getUserId();
        // 获取限流时间（秒）
        int time = rateLimit.time();
        // 获取限流次数
        int count = rateLimit.count();
        // 计算每秒允许的请求数
        double permitsPerSecond = (double) count / time;
        // 获取或创建 RateLimiter
        RateLimiter rateLimiter = rateLimiters.get(key, () -> RateLimiter.create(permitsPerSecond));
        // 尝试获取许可
        log.info("userId:{},rateLimiter:{}", key, rateLimiter);
        if (!rateLimiter.tryAcquire()) {
            // 未获取到许可，将用户加入黑名单
            blacklist.put(userId, blacklist.get(userId, ()-> 1L)+1);
            log.info("用户 {} 尝试加入黑名单，次数：{}", userId, blacklist.get(userId,()-> 1L));
            return true;
        }

        return false;
    }

    @Override
    protected boolean blacklistCheck(RateLimiterEntity rateLimiterEntity) throws ExecutionException {
        String userId = rateLimiterEntity.getUserId();
        // 检查用户是否在黑名单中  boolean 是否在黑名单中
        if(blacklist.get(userId,()->1l) >= 6) {
            return true;
        }
        return false;
    }
}
